﻿using SendMailServer.FileMatch;
using SendMailServer.Jike;
using SendMailServer.Search;
using SendMailServer.User;
using SendMailServer.WebSocket;
using SendMailServer.Wish;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
using WebSocketSharp.Server;

namespace SendMailServer
{
    public partial class AgSendMailWebSocket : ServiceBase
    {
        public AgSendMailWebSocket()
        {
            InitializeComponent();
        }

        public void Start()
        {
            OnStart(null);
        }
        protected override void OnStart(string[] args)
        {
            try
            {
                WSocket wSocket = new WSocket();
                wSocket.Start();
            }
            catch (Exception err)
            {
                File.WriteAllText("log.txt", "OnStart->" + err.Message);
            }
        }

        protected override void OnStop()
        {
        }
    }

    /// <summary>
    /// 服务端
    /// </summary>
    public class WSocket
    {
        //WebSocket对象
        public WebSocketServer _socketServer = null;
        List<WebSocketServiceHost> webSocketServiceHosts;
        public delegate bool SendDatas(string sData);
        public static event SendDatas SendDataEvent;
        public WSocket()
        {
            try
            {
                var t = File.ReadAllLines(@"D:\Program Files\SendMailServer\config.ini");
                var wsUrl = "";
                if (t.Length > 0)
                {
                    wsUrl = t[0];
                }
                Logger.WriteLine("准备建立WebSocket连接:"+t);
                //实例化
                _socketServer = new WebSocketSharp.Server.WebSocketServer(t[0]);
                //添加WebSocket的服务处理类
                _socketServer.AddWebSocketService<WSocketHandle>("/wsRobot");
                WebSocketServiceManager wSocketServiceManager = _socketServer.WebSocketServices;
                webSocketServiceHosts = wSocketServiceManager.Hosts.ToList();
            }
            catch (Exception err)
            {
                Logger.WriteLine("WSocket()->" + err.Message);
            }
        }

        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="Data"></param>
        public void SendData(string Data)
        {
            //第一种触发方式发送
            // SendDataEvent?.Invoke(Data);
            //第二种获取到session会话对象发送
            var session = webSocketServiceHosts[0].Sessions;//获取到session会话对象
            var sessionIds = session.ActiveIDs;//获取会话的IDs
            foreach (var sessionId in sessionIds)
            {
                //发送
                session.SendToAsync(Data, sessionId, new Action<bool>(t =>
                {
                    if (!t)
                    {
                        Console.WriteLine("发送失败");
                    }
                }));
            }
        }
        /// <summary>
        /// 启动
        /// </summary>
        public void Start()
        {
            _socketServer.Start();
        }
        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            _socketServer.Stop();
        }
    }

    /// <summary>
    /// Websoket的信息处理类
    /// </summary>
    public class WSocketHandle : WebSocketBehavior
    {
        private MailList m_mailManager = new MailList();
        public WSocketHandle()
        {
            WSocket.SendDataEvent += SendDataEvent;
        }
        /// <summary>
        /// 关闭触发
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClose(CloseEventArgs e)
        {
            Logger.WriteLine("连接断开：目前连接人数" + Sessions.Count);

        }
        /// <summary>
        /// 连接触发
        /// </summary>
        protected override void OnOpen()
        {
            Logger.WriteLine("连接成功：目前连接人数" + Sessions.Count);

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnError(WebSocketSharp.ErrorEventArgs e)
        {
            Logger.WriteLine("错误信息：" + e.Message);
        }
        
        /// <summary>
        /// 接收信息触发
        /// </summary>
        /// <param name="e"></param>
        protected override async void OnMessage(MessageEventArgs e)
        {
            try
            {
                string data = e.Data;
                if (m_mailManager.HandleLongWaitMesssage(data, (s2,e2) =>
                {
                    var s2e = s2 as ResMsg;
                    if(s2e != null)
                    {
                        SendMes(s2e, data);
                    }
                }))
                {
                    return;
                }
                var t2 = await m_mailManager.HandleMessage(data);

                if (FileMatchManager.SendFileMatchResource(t2, this, data))
                    return;
                SendMes(t2,data);
            }
            catch (Exception err)
            {
                Logger.WriteLine(err.Message + "\r\n" + err.StackTrace);
            }
        }

        #region 发生消息
        private void SendMes(ResMsg t2,string data)
        {
            if (t2.UseSelfResponse)
            {
                SendDataEvent(t2.MsgCode + ":" + t2.Content);
            }
            else
            {
                SendDataEvent(data + " -->" + t2.ToString());
            }
        }
        /// <summary>
        /// 发送信息事件
        /// </summary>
        /// <param name="sData"></param>
        /// <returns></returns>
        public bool SendDataEvent(string sData)
        {
            if (State == WebSocketState.Open)
            {
                if (Sessions.Count > 0)
                {
                    Send(sData);
                    return true;
                }
            }
            return false;
        } 
        #endregion

        #region 其他
        public static string GetContendDir(string appName)
        {
            return "D:\\Program Files\\SendMailServer\\content" + "_" + appName;
        }
        #endregion
    }

    public class MailList
    {
        internal static UserManager m_userMangaer = new UserManager();
        internal static JikeFileGetter jikeFileGetter = new JikeFileGetter();
        internal static CAPGetter capFileGetter = new CAPGetter();
        internal static ProgressRecorder progressRecorder = new ProgressRecorder();
        public MailList()
        {
            m_userMangaer.LoadUserFromDB();
        }

        public async Task<ResMsg> HandleMessage(string message)
        {
            var firstMH = message.IndexOf(':');
            if (firstMH<0)
            {
                return new ResMsg() { MsgCode = "unknow", IsOk = false, ErrorMsg = "不是处理的消息" };
            }
            var key = message.Substring(0,firstMH);
            var ts1 = message.Substring(firstMH + 1);

            if (key == "SendMail")
            {
                return m_userMangaer.SendMail(ts1);
            }
            if (key == "CheckState")
            {
                var keyValue = ts1.Split(',');
                var isValidUser = m_userMangaer.ValidUser(keyValue[0], keyValue[1]);
                if (isValidUser)
                {
                    return new ResMsg() { MsgCode = key, IsOk = true, Content = keyValue[2], AppName = keyValue[3] };
                }
                else
                {
                    return new ResMsg() { MsgCode = key, IsOk = false, Content = keyValue[2], AppName = keyValue[3], ErrorMsg = "没有匹配" };
                }
            }
            if (key == "UpdateServer")
            {
                UpdateServerUtil updateServerUtil = new UpdateServerUtil();
                var str = updateServerUtil.Update();
                return new ResMsg() { MsgCode = key, IsOk = str.StartsWith("OK"), ErrorMsg = str };
            }
            if (key == "GetLoginQuestion")
            {
                var examItem=ExamHelper.GetNextQuestion(ts1);
                if(examItem!=null)
                {
                    return new ResMsg()
                    {
                        MsgCode = key,
                        IsOk = true,
                        Content = examItem.ToFormatString(),
                        UseSelfResponse = true
                    };
                }
            }
            if(key== "GetPageViewCount")
            {
                var examItem = ExamHelper.GetPageViewCount(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }

            var r1=jikeFileGetter.LoadJikeFile(key,ts1);
            if (r1 != null) return r1;
            var r2= capFileGetter.LoadCAPFile(key);
            if(r2 != null) return r2;
            var r3 = capFileGetter.DeployCAPFile(key, ts1);
            if (r3 != null) return r3;
            var r4= WebSocketHelper.SendWebhookMsg(key, ts1);
            if(r4 != null) return r4;
            var r5= progressRecorder.HandlerMsg(key, ts1);
            if (r5 != null) return r5;
            var r6 = CodeSnip.HandlerMsg(key, ts1);
            if(r6 != null) return r6;
            var r7= MarkDownFile.HandlerMsg(key, ts1);
            if(r7 != null) return r7;
            var r8 = Wishboard.HandlerMsg(key, ts1);
            if (r8 != null) return r8;

            if (key == "SaveJikeFile")
            {
                var fileNameIndex = ts1.IndexOf(";");
                if (fileNameIndex != -1)
                {
                    var fileName = ts1.Substring(0, fileNameIndex);
                    var fileContent = ts1.Substring(fileNameIndex + 1);
                    var saveFileName = Path.Combine(JikeFileGetter.jkDir, fileName + ".html");
                    if(Directory.Exists(Path.GetDirectoryName(saveFileName))==false) {
                        Directory.CreateDirectory(Path.GetDirectoryName(saveFileName));
                    }
                    File.WriteAllText(saveFileName, fileContent, Encoding.GetEncoding("GBK"));
                }
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = "保存极客文章成功",
                    UseSelfResponse = true
                };
            }
            if (key == "GetJikeComments")
            {
                var examItem = ExamHelper.GetJikeComments(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }
            if (key == "SaveJikeComments")
            {
                var examItem = ExamHelper.SaveJikeComments(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }
            if (key == "GetJikeTagData")
            {
                var examItem = ExamHelper.GetJikeTagData(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }
            if (key == "SaveJikeTagData")
            {
                var examItem = ExamHelper.SaveJikeTagData(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }
            if (key == "SearchJikeTagData")
            {
                var examItem = ExamHelper.SearchJikeTagData(ts1);
                return new ResMsg()
                {
                    MsgCode = key,
                    IsOk = true,
                    Content = examItem,
                    UseSelfResponse = true
                };
            }
            if (key == "SearchMainContent")
            {
                var sc = new SearchMainContent();
                return sc.Search(key, ts1);
            }
            return new ResMsg() { MsgCode = key, IsOk = false, ErrorMsg = "其他状态" };
        }

        public bool HandleLongWaitMesssage(string message,EventHandler handler)
        {
            var firstMH = message.IndexOf(':');
            if (firstMH < 0)
            {
                return false;
            }
            var key = message.Substring(0, firstMH);
            var ts1 = message.Substring(firstMH + 1);
            if (key == "ChatGpt")
            {
                ChatGpt gpt = new ChatGpt();
                gpt.ChatAsync(key, ts1, handler);
                return true;
            }
            return false;
        }
    }

    public class ResMsg
    {
        public string MsgCode;
        public bool IsOk;
        public bool UseSelfResponse = false;
        public string ErrorMsg;
        public string Content;
        public string AppName;

        public override string ToString()
        {
            return MsgCode + ":" + (IsOk ? "OK" : "Error With " + ErrorMsg);
        }
    }
    

    public class UpdateServerUtil
    {
        Timer timer;
        internal string Update()
        {
            var fileName = "D:\\Program Files\\SendMailServer\\batchExe.txt";
            if (File.Exists(fileName) == false)
            {
                File.WriteAllText(fileName, "填写三个地址，第一个是更新server的.bat地址，第二个是UpdateDesktopDocHtmlContent.exe的地址，第三个是目录，是最终网站的html目录。三个地址用逗号分块");
                return "请到服务器中更新"+fileName;
            }
            string[] exeList=File.ReadAllText(fileName).Split(new char[] { ',' });
            if (File.Exists(exeList[0]) == false|| File.Exists(exeList[1]) == false|| Directory.Exists(exeList[2]) == false) {
                return "请到服务器中更新" + fileName+"，因为地址不存在";
            }

            CreateUpdateSign();
            //RunFunction(exeList[1], " i ");

            return "OK";
        }

        private void CreateUpdateSign()
        {
            string fileName = "D:\\Program Files\\SendMailServer\\t.txt";
            if (File.Exists(fileName) == false)
                File.WriteAllText(fileName, DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
        }

        private void RunFunction(string fileName, string argments)
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo(fileName);
            if (string.IsNullOrEmpty(argments) == false)
                processStartInfo.Arguments = argments;
            Process process = new Process();
            process.StartInfo = processStartInfo;
            process.StartInfo.UseShellExecute = true;
            process.Start();
        }
    }
}


 
